/**
 * 元素选择器工具类
 * 用于实现类似开发者工具的元素选择功能
 * 支持鼠标悬停预览和点击选择元素
 */
import { logger } from './logger';
import { LinkExtractor, NavigationLink } from './linkExtractor';

export class ElementSelector {
  private isActive: boolean = false;
  private currentElement: Element | null = null;
  private highlightElement: HTMLElement | null = null;
  private onSelectCallback: ((links: NavigationLink[]) => void) | null = null;

  /**
   * 构造函数
   * @param onSelect 选择元素回调函数
   */
  constructor(onSelect?: (links: NavigationLink[]) => void) {
    this.onSelectCallback = onSelect || null;
  }

  /**
   * 启动元素选择器
   */
  enable(): void {
    logger.info("启动元素选择器");
    this.isActive = true;
    this.createHighlightElement();
    this.attachEventListeners();
  }
  
  /**
   * 停止元素选择器
   */
  disable(): void {
    logger.info("停止元素选择器");
    this.isActive = false;
    this.removeHighlightElement();
    this.detachEventListeners();
  }
  
  /**
   * 创建高亮元素
   */
  private createHighlightElement(): void {
    logger.debug("创建高亮显示元素");
    this.highlightElement = document.createElement('div');
    this.highlightElement.id = 'nav-selector-highlight';
    this.highlightElement.style.position = 'absolute';
    this.highlightElement.style.border = '2px solid #ff0000';
    this.highlightElement.style.backgroundColor = 'rgba(255, 0, 0, 0.2)';
    this.highlightElement.style.pointerEvents = 'none';
    this.highlightElement.style.zIndex = '9999';
    this.highlightElement.style.display = 'none';
    document.body.appendChild(this.highlightElement);
  }
  
  /**
   * 移除高亮元素
   */
  private removeHighlightElement(): void {
    if (this.highlightElement && this.highlightElement.parentNode) {
      logger.debug("移除高亮显示元素");
      this.highlightElement.parentNode.removeChild(this.highlightElement);
      this.highlightElement = null;
    }
  }
  
  /**
   * 附加事件监听器
   */
  private attachEventListeners(): void {
    logger.debug("添加鼠标事件监听器");
    document.addEventListener('mousemove', this.handleMouseMove);
    document.addEventListener('click', this.handleClick, true);
    document.addEventListener('keydown', this.handleKeyDown);
  }
  
  /**
   * 移除事件监听器
   */
  private detachEventListeners(): void {
    logger.debug("移除鼠标事件监听器");
    document.removeEventListener('mousemove', this.handleMouseMove);
    document.removeEventListener('click', this.handleClick, true);
    document.removeEventListener('keydown', this.handleKeyDown);
  }
  
  /**
   * 处理鼠标移动事件
   */
  private handleMouseMove = (event: MouseEvent): void => {
    if (!this.isActive) return;
    
    const element = document.elementFromPoint(event.clientX, event.clientY);
    if (element === this.currentElement) return;
    
    this.currentElement = element;
    this.updateHighlight();
  }
  
  /**
   * 处理点击事件
   */
  private handleClick = (event: MouseEvent): void => {
    if (!this.isActive) return;
    
    event.preventDefault();
    event.stopPropagation();
    
    logger.info("选择了元素", this.currentElement);
    
    // 提取选中元素中的链接
    if (this.currentElement) {
      const links = LinkExtractor.extractLinksFromElement(this.currentElement);
      
      // 调用回调函数
      if (this.onSelectCallback) {
        this.onSelectCallback(links);
      }
      
      // 向后台脚本发送消息
      try {
        browser.runtime.sendMessage({
          action: 'selectedElementLinks',
          links: links
        });
      } catch (e) {
        logger.debug("发送消息到后台脚本失败", e);
      }
    }
    
    this.disable();
  }
  
  /**
   * 处理按键事件
   */
  private handleKeyDown = (event: KeyboardEvent): void => {
    if (!this.isActive) return;
    
    // ESC键取消选择
    if (event.key === 'Escape') {
      logger.info("按下ESC键，取消选择");
      this.disable();
      event.preventDefault();
    }
  }
  
  /**
   * 更新高亮显示
   */
  private updateHighlight(): void {
    if (!this.currentElement || !this.highlightElement) return;
    
    const rect = this.currentElement.getBoundingClientRect();
    this.highlightElement.style.top = `${window.scrollY + rect.top}px`;
    this.highlightElement.style.left = `${window.scrollX + rect.left}px`;
    this.highlightElement.style.width = `${rect.width}px`;
    this.highlightElement.style.height = `${rect.height}px`;
    this.highlightElement.style.display = 'block';
    
    logger.debug("更新高亮位置", {
      element: this.currentElement,
      rect: rect
    });
  }
} 